package cn.slipi.core.component.hystrix;

import cn.slipi.common.exception.InternalException;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.exception.HystrixRuntimeException;
import com.netflix.hystrix.exception.HystrixTimeoutException;
import cn.slipi.common.constants.Constants;
import cn.slipi.common.enums.RequestTypeEnum;
import cn.slipi.common.rule.custom.entity.MatchCondition;
import cn.slipi.core.plugin.IPluginChain;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * HttpCommandWebclient
 */
@Deprecated
public class HttpCommandWebclient extends HystrixCommand<Mono<Void>> {

    private static final Logger LOGGER = LoggerFactory.getLogger(HttpCommandWebclient.class);

    private static final WebClient WEB_CLIENT = WebClient.create();

    private final ServerWebExchange exchange;

    private final IPluginChain chain;

    private final MatchCondition condition;

    private final String url;

    private final long retry;

    public HttpCommandWebclient(final HystrixCommand.Setter setter,
                                final ServerWebExchange exchange,
                                final IPluginChain chain,
                                final MatchCondition condition,
                                final String url,
                                final long retry) {
        super(setter);
        this.exchange = exchange;
        this.chain = chain;
        this.condition = condition;
        this.url = url;
        this.retry = retry;
    }

    @Override
    protected Mono<Void> run() {
        if (StringUtils.equalsIgnoreCase(RequestTypeEnum.GET.getRequestType(), condition.getQueryType())) {
            LOGGER.debug("----------请求-----------");
            return WEB_CLIENT.get().uri(url)
                    .headers(httpHeaders -> {
                        httpHeaders.addAll(exchange.getRequest().getHeaders());
                        httpHeaders.remove(HttpHeaders.HOST);
                    })
                    .exchange()
                    .retry(retry)
                    .doOnError(this::dealError)
                    .flatMap(this::dealResponse);

        } else if (StringUtils.equalsIgnoreCase(RequestTypeEnum.POST.getRequestType(), condition.getQueryType())) {


        }

        return Mono.empty();
    }

    private Mono<Void> dealResponse(ClientResponse clientResponse) {
        HttpStatus httpStatus = clientResponse.statusCode();
        LOGGER.debug("-----------请求完成----------");
        if (httpStatus.is2xxSuccessful()) {
            exchange.getResponse().setStatusCode(HttpStatus.OK);
            exchange.getAttributes().put(Constants.WEBCLIENT_RESPONSE, clientResponse);
        } else {
            throw new InternalException(httpStatus.value(), httpStatus.getReasonPhrase());
        }
        return chain.execute(exchange);
    }

    @Override
    protected Mono<Void> getFallback() {
        final Throwable exception = getExecutionException();
        if (exception instanceof HystrixRuntimeException) {
            HystrixRuntimeException e = (HystrixRuntimeException) exception;
            if (e.getFailureType() == HystrixRuntimeException.FailureType.TIMEOUT) {
                exchange.getResponse().setStatusCode(HttpStatus.GATEWAY_TIMEOUT);
            } else {
                exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
            }
        } else if (exception instanceof HystrixTimeoutException) {
            exchange.getResponse().setStatusCode(HttpStatus.GATEWAY_TIMEOUT);
        } else {
            exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
        }
        return null;
    }

    private void dealError(Throwable e) {
        e.printStackTrace();
        throw new InternalException(HttpStatus.INTERNAL_SERVER_ERROR.value(), "接口请求异常");
    }

}
